package com.cheejee.goodscenter.service.impl;

import static com.cheejee.goodscenter.util.StaticField.SKU_SPECIFIC_SPLIT;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.carry.common.tool.ListTool;
import com.cheejee.goodscenter.dao.SkuMapper;
import com.cheejee.goodscenter.dao.SkuSnapshotMapper;
import com.cheejee.goodscenter.module.dto.SkuDto;
import com.cheejee.goodscenter.module.dto.SkuSnapshotDto;
import com.cheejee.goodscenter.module.dto.SkuSpecificDto;
import com.cheejee.goodscenter.module.entity.GoodsSpecific;
import com.cheejee.goodscenter.module.entity.Sku;
import com.cheejee.goodscenter.module.entity.SkuBrandProperties;
import com.cheejee.goodscenter.module.entity.SkuCategoryProperties;
import com.cheejee.goodscenter.module.entity.SkuCustomProperties;
import com.cheejee.goodscenter.module.entity.SkuSnapshot;
import com.cheejee.goodscenter.service.GoodsSpecificService;
import com.cheejee.goodscenter.service.SkuBrandPropertiesService;
import com.cheejee.goodscenter.service.SkuCategoryPropertiesService;
import com.cheejee.goodscenter.service.SkuCustomPropertiesService;
import com.cheejee.goodscenter.service.SkuService;
import com.cheejee.goodscenter.service.exception.CheckException;
import com.cheejee.goodscenter.service.exception.DataNotExistException;
import com.cheejee.goodscenter.service.exception.SystemError;
import com.cheejee.goodscenter.validated.Check;
import com.cheejee.goodscenter.validated.InsertGroup;
import com.cheejee.goodscenter.validated.UpdateGroup;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;

/**
 * @author CARRY
 * @Date 2020年10月28日下午11:17:55
 */
@Service
public class SkuServiceImpl implements SkuService {

	@Resource
	private SkuMapper mapper;

	@Resource
	private SkuSnapshotMapper ssm;

	@Resource
	private SkuBrandPropertiesService bps;

	@Resource
	private SkuCategoryPropertiesService cps;

	@Resource
	private SkuCustomPropertiesService mps;

	@Resource
	private GoodsSpecificService gss;

	@Override
	public Sku querySkuById(Long id) {

		return mapper.selectByPrimaryKey(id);
	}

	@Override
	public SkuDto querySkuInfoById(Long id) {
		Sku s = mapper.selectByPrimaryKey(id);
		if (s == null) {
			return null;
		}

		return convert(Arrays.asList(s)).get(0);
	}

	@Override
	public Page<Sku> querySku(Long goodsId, String goodsSpecificIdGroup, Boolean isOn, int pageNum, int pageSize) {

		return PageHelper.startPage(pageNum, pageSize).doSelectPage(() -> mapper.selectBySelective(goodsId, goodsSpecificIdGroup, isOn));
	}

	@Override
	public PageInfo<SkuDto> querySkuDto(Long goodsId, String goodsSpecificIdGroup, Boolean isOn, int pageNum, int pageSize) {
		PageHelper.startPage(pageNum, pageSize);

		return new PageInfo<SkuDto>(convert(mapper.selectBySelective(goodsId, goodsSpecificIdGroup, isOn)));
	}

	@Override
	@Transactional
	@Check(message = { "商品ID不能为空", "新增的SKU不能为空" }, group = InsertGroup.class)
	public int addSku(Long goodsId, List<SkuDto> sku) {
		ListTool.removeNull(sku);
		checkSkuDtoSpificGroup(sku);

		List<Sku> s = convert(goodsId, sku);
		checkSkuSpificGroup(s);
		int result = mapper.insertMany(s);
		for (int i = 0; i < s.size(); i++) {
			sku.get(i).setId(s.get(i).getId());
		}

		updateSnapshot(s);
		updateProperties(s, sku, true);

		return result;
	}

	@Override
	@Transactional
	@Check(message = { "商品ID不能为空", "商品SKU不能为NULL" }, group = UpdateGroup.class, IgnoreEmptyList = true)
	public int changeGoodsSku(Long goodsId, List<SkuDto> sku) {
		ListTool.removeNull(sku);
		if (CollectionUtil.isEmpty(sku)) {
			mapper.deleteByGoodsId(goodsId);
		}

		checkSkuDtoSpificGroup(sku);
		List<Sku> s = convert(goodsId, sku);
		updateSku(goodsId, s);
		updateSnapshot(s);
		updateProperties(s, sku, false);

		return 1;
	}

	@Override
	@Transactional
	@Check(message = { "商品ID不能为空", "修改的SKU不能为空" }, group = UpdateGroup.class)
	public int changeSkuinfo(Long goodsId, SkuDto sku) {
		if (mapper.selectByPrimaryKey(sku.getId()) == null) {
			throw new DataNotExistException("SKU不存在");
		}
		Sku s = convert(goodsId, Arrays.asList(sku)).get(0);
		mapper.updateByPrimaryKeySelective(s);
		updateSnapshot(Arrays.asList(s));
		
		List<SkuCategoryProperties> scp = sku.getCategoryProperties();
		if(!CollectionUtil.isEmpty(scp)) {
			Long[] ids = scp.stream().map(i -> i.getId()).toArray(Long[]::new);
			cps.deleteSkuCategoryProperties(ids);
			cps.addSkuCategoryProperties(scp);
		}
		
		List<SkuBrandProperties> sbp = sku.getBrandProperties();
		if(!CollectionUtil.isEmpty(sbp)) {
			Long[] ids = sbp.stream().map(i -> i.getId()).toArray(Long[]::new);
			bps.deleteSkuBrandProperties(ids);
			bps.addSkuBrandProperties(sbp);
		}
		
		List<SkuCustomProperties> smp = sku.getCustomProperties();
		if(!CollectionUtil.isEmpty(smp)) {
			Long[] ids = smp.stream().map(i -> i.getId()).toArray(Long[]::new);
			mps.deleteSkuCustomProperties(ids);
			mps.addSkuCustomProperties(smp);
		}
		
		return 0;
	}

	@Override
	@Check(message = "修改的SKU不能为空", group = UpdateGroup.class)
	public int changeSku(Sku sku) {
		checkExist(mapper, sku.getId());
		int i = mapper.updateByPrimaryKeySelective(sku);
		updateSnapshot(Arrays.asList(sku));

		return i;
	}

	@Override
	public int deleteSku(Long... id) {

		return mapper.deleteById(id);
	}

	private List<Sku> convert(Long goodsId, List<SkuDto> dto) {
		List<Sku> list = new ArrayList<>();

		if (CollectionUtil.isEmpty(dto)) {
			return list;
		}

		for (SkuDto i : dto) {
			StringBuilder sb = new StringBuilder();
			String spp = null;

			if (!CollectionUtil.isEmpty(i.getSpecific())) {
				for (SkuSpecificDto sp : i.getSpecific()) {
					List<GoodsSpecific> sc = gss.queryGoodsSpecific(goodsId, sp.getName(), sp.getValue(), 0, 0);

					if (CollectionUtil.isEmpty(sc)) {
						throw new DataNotExistException("SKU中关联了不存在的规格");
					}
					if (sc.size() != 1) {
						throw new SystemError("商品规格数据异常");
					}
					sb.append(sc.get(0).getId());
					sb.append(SKU_SPECIFIC_SPLIT);
				}
				spp = sb.substring(0, sb.length() - 1);
			}

			list.add(new Sku(i.getId(), goodsId, spp, i.getPrice(), i.getStock(), i.getPic(), i.getSale(), i.getIsOn(), i.getWebDetail(), i.getMobileDetail()));
		}

		return list;
	}

	public static String builderSpecificIdGroup(List<SkuSpecificDto> dto) {
		StringBuilder sb = new StringBuilder();
		for (SkuSpecificDto i : dto) {
			sb.append(i.getId());
			sb.append(SKU_SPECIFIC_SPLIT);
		}

		return sb.substring(0, sb.length() - 1);

	}

	private List<SkuDto> convert(List<Sku> sku) {
		List<SkuDto> ld = new ArrayList<SkuDto>();
		if (CollectionUtil.isEmpty(sku)) {
			return ld;
		}

		for (Sku i : sku) {
			List<SkuSpecificDto> sp = new ArrayList<SkuSpecificDto>();
			long[] sid = Stream.of(i.getGoodsSpecificIdGroup().split(SKU_SPECIFIC_SPLIT)).mapToLong(Long::parseLong).toArray();
			for (long l : sid) {
				GoodsSpecific gs = gss.queryGoodsSpecificById(l);
				sp.add(new SkuSpecificDto(gs.getId(), gs.getSpecificName(), gs.getSpecificValue()));
			}

			SkuDto d = new SkuDto();
			d.setId(i.getId());
			d.setPrice(i.getPrice());
			d.setStock(i.getStock());
			d.setPic(i.getPic());
			d.setSale(i.getSale());
			d.setIsOn(i.getIsOn());
			d.setWebDetail(i.getWebDetail());
			d.setMobileDetail(i.getMobileDetail());
			d.setSpecific(sp);
			d.setBrandProperties(bps.querySkuBrandProperties(i.getId(), null, null, 0, 0));
			d.setCategoryProperties(cps.querySkuCategoryProperties(i.getId(), null, null, 0, 0));
			d.setCustomProperties(mps.querySkuCustomProperties(i.getId(), null, 0, 0));
			ld.add(d);
		}
		return ld;
	}

	/**
	 * 判断规格组合是否重复，和数据库对比
	 *
	 * @param sku
	 */
	private void checkSkuSpificGroup(List<Sku> sku) {
		if (CollectionUtil.isEmpty(sku)) {
			return;
		}
		sku.forEach(i -> {
			if (mapper.selectSpecificGroupCount(i.getGoodsId(), i.getGoodsSpecificIdGroup()) != 0) {
				throw CheckException.builder().checkMessage("SKU的规格组合重复").build();
			}
		});
	}

	/**
	 * 判断SKU规格，list内判断： 1.判断规格组合是否重复 2.判断规格同名称是否多选 3.判断规格数量是否超过5
	 *
	 * @param sku
	 */
	private void checkSkuDtoSpificGroup(List<SkuDto> sku) {
		if (CollectionUtil.isEmpty(sku)) {
			return;
		}

		Set<String> st = new HashSet<>();
		for (SkuDto i : sku) {
			if (CollectionUtil.isEmpty(i.getSpecific())) {
				st.add("");
				continue;
			}
			st.add(i.getSpecific().toString());
			Set<String> ns = new HashSet<>();
			List<SkuSpecificDto> sp = i.getSpecific();
			if (sp.size() > 5) {
				throw new CheckException("SKU规格数量不能超过5");
			}

			sp.forEach(j -> {
				ns.add(j.getName());
			});

			if (sp.size() != ns.size()) {
				throw new CheckException("同名称的规格只能选择一个规格值");
			}
		}

		if (st.size() != sku.size()) {
			throw CheckException.builder().checkMessage("SKU的规格组合重复").build();
		}
	}

	public static void checkExist(SkuMapper mapper, Long id) {
		if (mapper.selectByPrimaryKey(id) == null) {
			throw new DataNotExistException("SKU不存在");
		}
	}

	/**
	 * 更新SKU属性
	 *
	 * @param sku   拥有ID的SKU
	 * @param dto   没ID的dot
	 * @param isAdd 如果是新增SKU则将此项设置为true。
	 */
	private void updateProperties(List<Sku> sku, List<SkuDto> dto, boolean isAdd) {
		if (CollectionUtil.isEmpty(sku) || CollectionUtil.isEmpty(dto) || sku.size() != dto.size()) {
			return;
		}

		for (int i = 0; i < sku.size(); i++) {
			Long skuId = sku.get(i).getId();
			dto.get(i).setId(skuId);

			if (!isAdd) {
				bps.deleteSkuBrandPropertiesBySku(skuId);
				cps.deleteSkuCategoryPropertiesBySku(skuId);
				mps.deleteSkuCustomPropertiesBySku(skuId);
			}

			SkuDto s = dto.get(i);
			List<SkuBrandProperties> b = s.getBrandProperties();
			List<SkuCategoryProperties> c = s.getCategoryProperties();
			List<SkuCustomProperties> m = s.getCustomProperties();

			if (!CollectionUtil.isEmpty(b)) {
				b.forEach(p -> p.setSkuId(skuId));
				bps.addSkuBrandProperties(b);
			}

			if (!CollectionUtil.isEmpty(c)) {
				c.forEach(p -> p.setSkuId(skuId));
				cps.addSkuCategoryProperties(c);
			}

			if (!CollectionUtil.isEmpty(m)) {
				m.forEach(p -> p.setSkuId(skuId));
				mps.addSkuCustomProperties(m);
			}
		}
	}

	private void updateSku(Long goodsId, List<Sku> sku) {
		List<Sku> list = new ArrayList<>(sku);
		List<Sku> add = list.stream().filter(i -> i.getId() == null).collect(Collectors.toList());
		list.removeAll(add);

		List<Long> nid = list.stream().map(i -> i.getId()).collect(Collectors.toList());
		List<Long> oid = mapper.selectBySelective(goodsId, null, null).stream().map(i -> i.getId()).collect(Collectors.toList());
		oid.removeAll(nid);

		if (oid.size() != 0) {
			mapper.deleteById(oid.toArray(new Long[oid.size()]));
		}
		if (add.size() != 0) {
			mapper.insertMany(add);
		}
		list.forEach(i -> {
			if (mapper.selectByPrimaryKey(i.getId()) == null) {
				throw new DataNotExistException("SKU不存在");
			}
		});
		list.forEach(i -> mapper.updateByPrimaryKeySelective(i));
	}

	private void updateSnapshot(List<Sku> sku) {
		if (CollectionUtil.isEmpty(sku)) {
			return;
		}

		ListTool.removeNull(sku);
		for (Sku f : sku) {
			Sku d = mapper.selectByPrimaryKey(f.getId());
			if (d == null) {
				continue;
			}

			List<SkuSpecificDto> sp = new ArrayList<>();
			long[] sid = Stream.of(d.getGoodsSpecificIdGroup().split(SKU_SPECIFIC_SPLIT)).mapToLong(Long::parseLong).toArray();
			for (long l : sid) {
				GoodsSpecific gs = gss.queryGoodsSpecificById(l);
				sp.add(new SkuSpecificDto(gs.getId(), gs.getSpecificName(), gs.getSpecificValue()));
			}

			SkuSnapshotDto s = BeanUtil.copyProperties(d, SkuSnapshotDto.class, "id", "specific");
			s.setSkuId(d.getId());
			s.setSpecificGroup(sp);
			SkuSnapshot ss = SkuSnapshotServcieImpl.convertDto(s);
			ss.setVersion(mapper.selectVersion(d.getId()));
			ssm.insertSelective(ss);
		}
	}

}
